import org.junit.Test;

import java.nio.ByteBuffer;

/**
 * @program: nio-learning
 * @description: 缓冲区测试
 * @author: zhaoxianglong
 * @create: 2021-03-08 10:22
 * @other buffer(缓冲区): 在java nio 中负责数据存取 . 底层以数组方式实现
 * ByteBuffer  CharBuffer ShortBuffer ......
 * 通过allocate() 获取缓冲区
 * @other Buffer主要方法
 * put() : 存储数据到缓冲区
 * get() : 读取缓冲区数据
 * @other Buffer 核心属性
 * capacity : 容量, 即创建缓冲区时数组最大容量, 一旦定义无法改变
 * limit : 界限, 缓冲区中可操作数组最大下标(put时等于capacity , get时为缓冲区已存数据最大下标)
 * position :  位置, 当前操作到缓冲区数据下标
 * mark : 标记, 可标记当前position位置 , 通常与reset()一同使用,用于恢复到mark标记位置进行读写
 * 注: 正常情况下 position <= limit <= capacity
 **/
public class TestBuffer {

    /**
     * 测试1: 以ByteBuffer为例对缓冲区进行操作
     */
    @Test
    public void test1() {
        //大小已指定
        ByteBuffer allocate = ByteBuffer.allocate(1024);

        System.out.println("缓冲区当前操作位置为: " + allocate.position());
        System.out.println("缓冲区可操作数组大小为: " + allocate.limit());
        System.out.println("缓冲区最大容量为: " + allocate.capacity());

        //利用put方法存储数据到缓冲区
        allocate.put(new byte[]{1, 2, 4});

        //重新打印
        System.out.println("--------我是分割线----------");
        System.out.println("缓冲区当前操作位置为: " + allocate.position());
        System.out.println("缓冲区可操作数组大小为: " + allocate.limit());
        System.out.println("缓冲区最大容量为: " + allocate.capacity());

        //切换缓冲区到读模式
        allocate.flip();

        //重新打印
        System.out.println("--------我是分割线----------");
        System.out.println("缓冲区当前操作位置为: " + allocate.position());
        System.out.println("缓冲区可操作数组大小为: " + allocate.limit());
        System.out.println("缓冲区最大容量为: " + allocate.capacity());

        ByteBuffer buffer = allocate.get(new byte[]{0, 1, 2});

        //重新打印
        System.out.println("--------我是分割线----------");
        System.out.println("缓冲区当前操作位置为: " + allocate.position());
        System.out.println("缓冲区可操作数组大小为: " + allocate.limit());
        System.out.println("缓冲区最大容量为: " + allocate.capacity());

        //可重复读
        allocate.rewind();

        //重新打印
        System.out.println("--------我是分割线----------");
        System.out.println("缓冲区当前操作位置为: " + allocate.position());
        System.out.println("缓冲区可操作数组大小为: " + allocate.limit());
        System.out.println("缓冲区最大容量为: " + allocate.capacity());

        //清空缓冲区
        allocate.clear();

        //重新打印
        System.out.println("--------我是分割线----------");
        System.out.println("缓冲区当前操作位置为: " + allocate.position());
        System.out.println("缓冲区可操作数组大小为: " + allocate.limit());
        System.out.println("缓冲区最大容量为: " + allocate.capacity());
    }

    /**
     * 测试2 : 已ByteBuffer为例测试mark标记
     */
    @Test
    public void test2() {

        String str = "12345";
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        buffer.put(str.getBytes());

        buffer.flip();

        byte[] bytes = new byte[buffer.limit()];
        buffer.get(bytes, 0, 2);
        System.out.println(new String(bytes, 0, 2));
        System.out.println(buffer.position());

        //标记
        buffer.mark();


        buffer.get(bytes, 2, 2);
        System.out.println(new String(bytes, 2, 2));
        System.out.println(buffer.position());

        //回退
        buffer.reset();

        System.out.println(buffer.position());

        //判断缓冲区中是否还有剩余的可操作数据
        if (buffer.hasRemaining()) {
            //输出缓冲区中可操作数据的数量
            System.out.println(buffer.remaining());
        }
    }

    /**
     * allocate() : 在jvm虚拟机中创建缓冲区
     * allocateDirect() : 在物理内存中创建缓冲区
     *
     */
    @Test
    public void test3(){
        ByteBuffer allocate = ByteBuffer.allocate(1024);
        ByteBuffer allocateDirect = ByteBuffer.allocateDirect(1024);
        System.out.println(allocate.isDirect());
        System.out.println(allocateDirect.isDirect());
    }
}
